#pragma once

#include <stdint.h>
#include <vector>
#include <map>
#include <string>
#include <string_view>
#include <ostream>

class DynamicObjImpl;

class DynamicObj
{
public:
    DynamicObj();

    DynamicObj(int32_t n);

    DynamicObj(const char *str)
        : DynamicObj(std::string_view(str)) {
    }

    DynamicObj(const std::string &str);

    DynamicObj(const std::string_view &str);

    DynamicObj(std::string &&str);

    DynamicObj(const std::vector<DynamicObj> &vec);

    DynamicObj(const std::map<std::string, DynamicObj> &map);

    DynamicObj(const std::string &name, const DynamicObj &value)
        : DynamicObj(std::map<std::string, DynamicObj>({ std::pair(name, value) })) {
    }

    ~DynamicObj();

    DynamicObj &operator=(const DynamicObj &other);

    void print(std::ostream &out) const;

private:
    void free();

private:
    DynamicObjImpl *impl_;
};

inline std::ostream &operator<<(std::ostream &out, const DynamicObj &obj) {
    obj.print(out);
    return out;
}
